from typing import TypeAlias, Generator

from puzzle.mathF import Vec2

from puzzle.board import Board
from puzzle.component import Transform, Component, ComponentSet
from puzzle.tile import TileDesc

from solver.SBoard import SBoard
from solver.SComponent import SComponent


def make_sboard(board: "Board") -> SBoard:
    bd = [[-1 for _ in range(length)] for length in board.row_length]

    x_map: list[list[int]] = [[0 for _ in range(length)] for length in board.row_length]
    y_map: list[list[int]] = [[0 for _ in range(length)] for length in board.row_length]
    
    row_map: list[list[int]] = [[0 for _ in range(6)] for __ in range(11)]
    col_map: list[list[int]] = [[0 for _ in range(6)] for __ in range(11)]

    for row in range(6):
        for col in range(board.row_length[row]):
            td = board.tiles[row][col]
            if td.tile.is_blank:
                bd[row][col] = -2
            
            x, y = td.special_x_index, td.row

            x_map[row][col] = x
            y_map[row][col] = y
            
            row_map[x][y] = row
            col_map[x][y] = col
    
    return SBoard(board, bd, x_map, y_map, row_map, col_map)
    
def make_blank(sb: "SBoard", tile: "TileDesc") -> None:
    sb.bd[tile.row][tile.col] = -2
    
def _get_xy(td: "TileDesc") -> tuple[float, float]:
    return td.special_x_index, td.row

def make_scomponents(transforms: list["Transform"]) -> list[SComponent]:
    ret = []
    
    for trans in transforms:
        ox, oy = _get_xy(trans.td[0])
        
        destx, desty = [], []
        for i in range(1, len(trans.td)):
            dx, dy = _get_xy(trans.td[i])
            destx.append(dx - ox)
            desty.append(dy - oy)

        ret.append(
            SComponent(trans.td[0].is_facing_up, len(trans.td)-1, destx, desty)
        )
    return ret

# def make_scomponents_auto(transform: "Transform") -> list[SComponent]:
#     ret = []
#     visited = []
    
#     # Rot 0
#     base_sc = make_scomponents_full([transform])[0]
#     facing = [td.is_facing_up for td in transform.td]
    
#     for r in range(1, 6):
#         facing = [not b for b in facing]
        
#         # New origin
#         nox, noy = 0, 0
#         oindex = -1
        
#         destx, desty = [], []
#         for i in range(base_sc.ndest):
#             destv = Vec2(base_sc.destx[i], base_sc.desty[i]).rotate(60 * r)
            
#             destx.append(destv.x)
#             desty.append(destv.y)
            
#             if (destv.y < noy) or (destv.y == noy and destv.x < nox):
#                 oindex = i
#                 noy = destv.y
#                 nox = destv.x

#         if oindex == -1:
#             f = facing[0]
#         else:
#             # Got new origin
#             f = facing[oindex + 1]
#             destx = destx[oindex:] + destx[oindex+1:] + [0]
#             desty = desty[oindex:] + desty[oindex+1:] + [0]
            
#             for i in range(base_sc.ndest):
#                 destx[i] -= nox
#                 desty[i] -= noy
        
#         sc = SComponent(f, base_sc.ndest, destx, desty)
#         if sc.dest_sorted not in visited:
#             visited.append(sc.dest_sorted)
#             ret.append(
#                 SComponent(f, base_sc.ndest, destx, desty)
#             )
#     return ret